package com.enzoism.springboot.dive.a01callable.a05asyafterexecute;

import com.enzoism.springboot.dive.common.BisException;

import java.util.concurrent.*;

/**
 * 自定义ThreadPoolExecutor,然后重写afterExecute()方法
 * 1）只要是使用了线程池
 * 2）不论是callable/runnable/thread都可以用这种方法捕获异常
 */
public class MyThreadPoolExecutor extends ThreadPoolExecutor {
    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
    }

    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }

    /**
     * 重写afterExecute的目的：
     * 1）不管是Runnable/Thread/Callable都是异步执行
     * 2）如果没有显示的调用get()方法，没有办法感知异常的产生
     * 3）如果在这个地方手动进行take()去感知异常
     * 4）成本：以前的异步任务提交即结束，不用等待take()结果，等待线程完成的时间是没有的，现在增加了
     * 5）缺点1：如果当前任务的耗时是很长的，那么感知异常的代价是很大的（需要合理分配是否需要感知异常）
     * 6）缺点2：如果传入的是Callable，在执行结束之后，结果就被take()，程序就没有办法再take()了.
     * 7）缺点3：没有办法进行返回值替换，但是可以抛出自定义异常
     */
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        if (t == null && r instanceof Future) {
            try {
                Object result = ((Future) r).get();
                System.out.println("---------MyThreadPoolExecutor-AfterExecute：" + result);
            } catch (CancellationException ce) {
                t = ce;
            } catch (ExecutionException ee) {
                t = ee.getCause();
//                throw new BisException(BisConstant.ERROR_FILTER_MSG);
            } catch (InterruptedException ie) {
                // ignore/reset
                Thread.currentThread().interrupt();
            } catch (BisException be) {
                t = be.getCause();
                System.out.println("--------进行自定义异常抛出");
            }
        }
        if (t != null) {
            t.printStackTrace();
        }
    }
}
